<!DOCTYPE html>
<html lang="en">
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://unpkg.com/konva@4.0.0/konva.min.js"></script>
    <script src="https://cdn.staticfile.org/vue/2.7.0/vue.min.js"></script>
  </head>
  <body>
    <!-- <div id="container"></div> -->
    <canvas id="canvas" width="500" height="500"></canvas>

    <div id="app">
      <input type="range" v-model="range" min="-100" max="100" />
      {{range}}
    </div>
  </body>

  <script>
    new Vue({
      el: "#app",
      data: {
        range: 0,
        fontSize: 20,
        text: "hello123123",
        canvasWidth: 250,
        textWidth: 0,
        textHeight: 0,
        circle: {
          x: 250,
          y: 250,
        },
      },
      created() {
        var q = 100;
        let canvas = document.getElementById("canvas");
        let context = canvas.getContext("2d");
        this.context = context;

        var text = this.text;
        this.calLen();
        var radius = this.calRadius();

        this.drawCircularText(
          context,
          text,
          this.calStart(radius),
          this.calEnd(radius),
          radius
        );
      },
      watch: {
        range() {
          this.onChange();
        },
      },
      methods: {
        onChange() {
          this.clear(this.context);
          let radius = this.calRadius();
          this.drawCircularText(
            this.context,
            this.text,
            this.calStart(radius),
            this.calEnd(radius),
            radius
          );
        },

        calLen() {
          let text = ` ${this.text} `;
          let metrics = this.context.measureText(text);
          this.textWidth = metrics.width;
          this.textHeight =
            metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
          this.text = text;
          console.log(
            `textWidth = ${this.textWidth} textHeight =${this.textHeight}`
          );
        },
        calStart(radius) {
          let l = this.textWidth;
          let a = (this.range * 360) / 100;

          let res = this.range > 0 ? a / 2 + 90 : a / 2 - 90;
          console.log(`calStart ${l} ${a} ${res}`);
          let offset = this.range > 0 ? radius : -radius;
          this.circle.y = this.canvasWidth + offset;
          // console.log(
          //   `y=${this.circle.y} ,yy=${Math.cos(-a * (Math.PI / 180)) * radius}`
          // );
          return res;
        },

        calEnd(radius) {
          let l = this.textWidth;
          let a = (this.range * 360) / 100;
          let res = this.range > 0 ? -a / 2 + 90 : -a / 2 - 90;
          console.log(`calEnd ${l} ${a} ${res}`);
          return res;
        },
        calRadius() {
          if (this.range == 0) {
            return 0;
          }
          let r = (180 * this.textWidth * 100) / this.range / 360;
          r = r > 0 ? r : -r;
          if (this.range > 0) {
            r -= this.textHeight;
          }
          console.log(`radius = ${r}`);
          return r;
        },
        clear(context) {
          context.clearRect(0, 0, 500, 500);
        },

        drawCircularText(context, string, startAngle, endAngle, radius) {
          let index = 0;
          context.textAlign = "center";
          context.textBaseLine = "middle";
          context.fillStyle = "rgba(0,0,0,0.5)";
          context.font = `${this.fontSize}px Lucida Sans`;

          if (this.range == 0) {
            while (index < string.length) {
              character = string.charAt(index);
              // let metrics = context.measureText(character+" ");
              // var letterWidth = metrics.width;
              let letterWidth = this.textWidth / string.length;
              context.save();
              context.beginPath();
              context.translate(
                this.canvasWidth - this.textWidth + letterWidth * index,
                this.canvasWidth
              );
              context.fillText(character, 0, 0);
              index++;
              context.restore();
            }
            return;
          }
          context.fillRect(this.circle.x, this.circle.y, 2, 2);

          let itemAngle = (startAngle - endAngle) / (string.length - 1); //每个字母占的弧度
          let angle = startAngle; //
          console.log(`itemAngle = ${itemAngle}`);
          while (index < string.length) {
            // console.log(index, angle, Math.cos((Math.PI / 180) * angle));

            character = string.charAt(index);
            context.save();
            context.beginPath();
            context.translate(
              this.circle.x + Math.cos((Math.PI / 180) * angle) * radius,
              this.circle.y - Math.sin((Math.PI / 180) * angle) * radius
            );
            let r = this.range > 0 ? angle : angle + 180;
            context.rotate(Math.PI / 2 - (Math.PI / 180) * r);
            context.fillText(character, 0, 0);
            // context.strokeText(character, 0, 0);
            angle -= itemAngle;

            index++;
            context.restore();
          }
          context.restore();
        },
      },
    });
  </script>

  <style>
    body {
      margin: 0;
      padding: 0;
      overflow: hidden;
      background-color: #f0f0f0;
    }
  </style>
</html>
